package game.module.nn.logic;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import game.RoomServer;
import game.entity.PlayingRole;
import game.lan.msg.NnStart2HsMessage;
import game.module.RoomType;
import game.module.ddz.bean.DdzLanPlayerInfo;
import game.module.nn.NnConstants;
import game.module.nn.bean.NnRound;
import game.module.user.dao.LanSessionCache;
import game.session.SessionManager;
import io.netty.channel.Channel;
import lion.common.ArrayUtility;
import lion.math.RandomDispatcher;
import lua.LuaMessageNn.NnPaiInfo;
import lua.LuaMessageNn.NnRoundScore;
import lua.LuaMessageNn.PushNNNewRound;
import lua.LuaMessageNn.PushNnRoundEnd;

public class NnLogic {

	private static Logger logger = LoggerFactory.getLogger(NnLogic.class);

	static class SingletonHolder {
		static NnLogic instance = new NnLogic();
	}

	public static NnLogic getInstance() {
		return SingletonHolder.instance;
	}
	public void sendNnJindouRoomChargeFee(int jindouDi, List<Integer> players) {
		logger.info("nn jindou room charge room fee");
		String rsLanHost = RoomServer.getInstance().getServerConfig().getHallLanhost();

		int rsLanPort = RoomServer.getInstance().getServerConfig().getHallLanport();
		boolean reconnectRet = RoomServer.getInstance().getLanClientManager().connect(rsLanHost, rsLanPort);
		if(reconnectRet) {
			RoomServer.getInstance().getLanClientManager().sendCalculateJindouFee(rsLanHost,rsLanPort,jindouDi,players);
		}else {
			logger.error("connect 2 roomServer error!rsLanHost={},rsLanPort={}", rsLanHost, rsLanPort);
		}
		
	}
	public void sendNnCalculatteHallServer(int score[], List<Integer> players, int gold_coin, String roomid,
			short roundcount, int room_type) {
		logger.info("nn jindou room  calculate room jindou ");
		String rsLanHost = RoomServer.getInstance().getServerConfig().getHallLanhost();

		int rsLanPort = RoomServer.getInstance().getServerConfig().getHallLanport();
		boolean reconnectRet = RoomServer.getInstance().getLanClientManager().connect(rsLanHost, rsLanPort);
		if (reconnectRet) {
			RoomServer.getInstance().getLanClientManager().sendCalculateHallServer(rsLanHost, rsLanPort, score, players,
					gold_coin, roomid, roundcount, room_type);
		} else {
			logger.error("connect 2 roomServer error!rsLanHost={},rsLanPort={}", rsLanHost, rsLanPort);
		}
	}

	
	public void generateCards(Channel channel, String roomId, List<DdzLanPlayerInfo> playerList, short round_count,
			byte roomFeeType, int roomFee, byte is_jindou, int jindou) {
		logger.info("nn generate cards,playerList={}", playerList);
		int playerCount = playerList.size();
		NnRound ddzRound = new NnRound();
		randCard(ddzRound, playerCount);
		ddzRound.setRoomFee(roomFee);
		ddzRound.setRoomFeeType(roomFeeType);
		ddzRound.setRoomUuid(roomId);
		ddzRound.setRoundCount(1);
		ddzRound.setRoundSum(round_count);
		ddzRound.setIs_jindou(is_jindou);
		ddzRound.setJindou(jindou);
		ddzRound.setScore(new short[playerList.size()]);
		ddzRound.setVotediss(new boolean[playerList.size()]);
		NnStart2HsMessage respMsg = new NnStart2HsMessage(channel.alloc());
		respMsg.writeString(roomId);
		respMsg.writeInt(playerCount);
		for (int i = 0; i < playerCount; i++) {
			int playerId = playerList.get(i).getPlayerId();
			List<Byte> aPlayerCards = ddzRound.getCards().get(i);
			respMsg.writeInt(playerId);
			respMsg.writeInt(aPlayerCards.size());
			for (Byte aCard : aPlayerCards) {
				respMsg.writeByte(aCard);
			}
		}
		// 抢庄家次数
		ddzRound.setLoopCount(0);
		// 缓存玩家信息
		List<Integer> playerIds = new ArrayList<>();
		ddzRound.setPlayerIds(playerIds);
		for (DdzLanPlayerInfo ddzLanPlayerInfo : playerList) {
			LanSessionCache.getInstance().addSession(ddzLanPlayerInfo.getSessionId(), ddzLanPlayerInfo.getPlayerId());
			playerIds.add(ddzLanPlayerInfo.getPlayerId());
		}
		// 缓存牌局信息
		for (DdzLanPlayerInfo ddzLanPlayerInfo : playerList) {
			NnDataManager.getInstance().addRoundCache(ddzLanPlayerInfo.getPlayerId(), ddzRound);
		}
		long create_time = System.currentTimeMillis();
		ddzRound.setCreate_time(create_time);
		if(ddzRound.getIs_jindou()==1) {//金豆房扣钱
			sendNnJindouRoomChargeFee(ddzRound.getJindou(),ddzRound.getPlayerIds());
		}
		channel.writeAndFlush(respMsg);
	}

	private void randCard(NnRound ddzRound, int playerCount) {
		RandomDispatcher<Byte> rd = new RandomDispatcher<>();
		for (short i = 0; i < NnConstants.cardData.length; i++) {
			rd.put(1, NnConstants.cardData[i]);
		}
		List<List<Byte>> cards = new ArrayList<>();
		ddzRound.setCards(cards);
		for (int i = 0; i < playerCount; i++) {
			List<Byte> aPlayerCards = new ArrayList<>();
			for (int j = 0; j < 4; j++) {
				aPlayerCards.add(rd.randomRemove());
			}
			cards.add(aPlayerCards);
		}
		ddzRound.setFaPaiTool(rd);
	}

	/**
	 * 牛牛结算
	 * 
	 * @param ddzRound
	 */
	public void claculateResult(NnRound ddzRound) {
		int zhuangJiaIndex = ddzRound.getZhuangJiaIndex();
		List<List<Byte>> cardList = ddzRound.getCards();
		// 玩家所有牌的信息
		NnPaiInfo[] pai_list = new NnPaiInfo[cardList.size()];
		for (int i = 0; i < cardList.size(); i++) {
			int myPlayerId = ddzRound.getPlayerIds().get(i);
			List<Byte> myCards = cardList.get(i);
			pai_list[i] = new NnPaiInfo();
			pai_list[i].cards = ArrayUtility.toByteArray(myCards);
			pai_list[i].niu_10_cards = ddzRound.getPeiPaiFinish().get(myPlayerId);
		}
		// 分数信息
		short[] scoreAll = new short[cardList.size()];
		for (int i = 0; i < cardList.size(); i++) {
			int myPlayerId = ddzRound.getPlayerIds().get(i);
			List<Byte> myCards = cardList.get(i);
			// 庄家处理
			if (i == zhuangJiaIndex) {
				// push
				short mySumScore = 0;
				for (int j = 0; j < cardList.size(); j++) {
					if (i == j) {
						continue;
					}
					int otherScore = ddzRound.getZhuangJiaRate() * ddzRound.getXianJiaXiaZhu().get(j);
					List<Byte> otherCards = cardList.get(j);
					byte[] myCards_raw = ArrayUtility.toByteArray(myCards);
					byte[] otherCards_raw = ArrayUtility.toByteArray(otherCards);
					int oxTimes = getOxTimes(myCards_raw, otherCards_raw);
					otherScore *= oxTimes;
					boolean FirstOX = NnAlgorithm.getInstance().GetOxCard(myCards_raw, NnConstants.MAX_COUNT);
					boolean NextOX = NnAlgorithm.getInstance().GetOxCard(otherCards_raw, NnConstants.MAX_COUNT);
					boolean isMyBigger = NnAlgorithm.getInstance().CompareCard(myCards_raw, otherCards_raw,
							NnConstants.MAX_COUNT, FirstOX, NextOX);
					if (isMyBigger) {
						mySumScore += otherScore;
					} else {
						mySumScore -= otherScore;
					}
				}
				scoreAll[i] = mySumScore;
			} else {// 闲家处理
				int myScore = ddzRound.getZhuangJiaRate() * ddzRound.getXianJiaXiaZhu().get(i);
				List<Byte> zhuangJiaCards = cardList.get(zhuangJiaIndex);
				byte[] myCards_raw = ArrayUtility.toByteArray(myCards);
				byte[] zhuangJiaCards_raw = ArrayUtility.toByteArray(zhuangJiaCards);
				int oxTimes = getOxTimes(myCards_raw, zhuangJiaCards_raw);
				myScore *= oxTimes;
				boolean FirstOX = NnAlgorithm.getInstance().GetOxCard(myCards_raw, NnConstants.MAX_COUNT);
				boolean NextOX = NnAlgorithm.getInstance().GetOxCard(zhuangJiaCards_raw, NnConstants.MAX_COUNT);
				boolean isMyBigger = NnAlgorithm.getInstance().CompareCard(myCards_raw, zhuangJiaCards_raw,
						NnConstants.MAX_COUNT, FirstOX, NextOX);
				if (!isMyBigger) {
					myScore = -myScore;
				}
				scoreAll[i] = (short) myScore;
			}

		}
		if (ddzRound.getScore() == null) {
			ddzRound.setScore(scoreAll);
		} else {
			short socres[] = ddzRound.getScore();
			for (int j = 0; j < socres.length; j++)
				socres[j] += scoreAll[j];
		}
		if (ddzRound.getIs_jindou() == 1) {// 金豆房间结算
			//short score[] =ArrayUtility.
			//		ddzRound.getScore();
			//ArrayUtility.long2Int(sssRound.m_lGameScore);
			int[] score = ArrayUtility.short2Int(ddzRound.getScore());;
			int roundcount = ddzRound.getRoundCount();
			sendNnCalculatteHallServer(score, ddzRound.getPlayerIds(), ddzRound.getJindou(), ddzRound.getRoomUuid(),
					(short)roundcount, RoomType.NnRoom);
		}
		// 发送消息
		for (int i = 0; i < cardList.size(); i++) {
			int myPlayerId = ddzRound.getPlayerIds().get(i);
			// 庄家处理
			if (i == zhuangJiaIndex) {
				// push
				PushNnRoundEnd pushMsg = new PushNnRoundEnd();
				pushMsg.player_score = scoreAll;
				pushMsg.pai_list = pai_list;
				pushMsg.score_list = new NnRoundScore[cardList.size() - 1];
				int msgIdx = 0;
				for (int j = 0; j < cardList.size(); j++) {
					if (i == j) {
						continue;
					}
					int otherPlayerId = ddzRound.getPlayerIds().get(j);
					short otherScore = scoreAll[j];
					NnRoundScore nnRoundScore = new NnRoundScore(otherPlayerId, (short) Math.abs(otherScore),
							NnConstants.BYTE_NO);
					pushMsg.score_list[msgIdx++] = nnRoundScore;
					if (otherScore > 0) {
						nnRoundScore.get_or_send = NnConstants.BYTE_YES;
					}
				}
				PlayingRole pr = SessionManager.getInstance().getPlayer(myPlayerId);
				if (pr != null && pr.isChannelActive()) {
					pr.writeAndFlush(pushMsg.build(pr.alloc()));
				}
			} else {// 闲家处理
				short myScore = scoreAll[i];
				int zhuangJiaId = ddzRound.getPlayerIds().get(zhuangJiaIndex);
				// push
				PushNnRoundEnd pushMsg = new PushNnRoundEnd();
				pushMsg.player_score = scoreAll;
				pushMsg.pai_list = pai_list;
				pushMsg.score_list = new NnRoundScore[1];
				pushMsg.score_list[0] = new NnRoundScore(zhuangJiaId, (short) Math.abs(myScore), NnConstants.BYTE_NO);
				if (myScore < 0) {
					pushMsg.score_list[0].get_or_send = NnConstants.BYTE_YES;
				}
				PlayingRole pr = SessionManager.getInstance().getPlayer(myPlayerId);
				if (pr != null && pr.isChannelActive()) {
					pr.writeAndFlush(pushMsg.build(pr.alloc()));
				}
			}
		}
	}

	private int getOxTimes(byte[] myCards_raw, byte[] otherCards_raw) {
		byte myTimes = NnAlgorithm.getInstance().GetTimes(myCards_raw, (byte) myCards_raw.length);
		byte otherTimes = NnAlgorithm.getInstance().GetTimes(otherCards_raw, (byte) otherCards_raw.length);
		return Math.max(myTimes, otherTimes);
	}

	public void nextRound(NnRound ddzRound) {
		if (ddzRound.getRoomFee() > 0 && ddzRound.getRoomFeeType() != 2) {
			int fee = ddzRound.getRoomFee();
			sendNnCalculateFangka((short) fee, ddzRound.getRoomFeeType(), ddzRound.getPlayerIds());// 一局结算扣钱
			ddzRound.setRoomFee(0);
		} // 数据重置
		if(ddzRound.getIs_jindou()==1) {//牛牛金豆房间房费扣取
			sendNnJindouRoomChargeFee(ddzRound.getJindou(),ddzRound.getPlayerIds());
		}
		ddzRound.getCards().clear();
		// 抢庄家次数
		ddzRound.setLoopCount(0);
		ddzRound.setRoundCount(ddzRound.getRoundCount() + 1);
		randCard(ddzRound, ddzRound.getPlayerIds().size());
		ddzRound.setLastJiaoScore(null);
		ddzRound.setZhuangJiaIndex(null);
		ddzRound.setZhuangJiaRate(null);
		ddzRound.getQiangZhuangJiaInfoList().clear();
		ddzRound.getXianJiaXiaZhu().clear();
		ddzRound.getPeiPaiFinish().clear();
		// 发送消息
		List<Integer> playerIds = ddzRound.getPlayerIds();
		PushNNNewRound pushMsg = new PushNNNewRound();
		int playerIndex = 0;
		for (Integer aPlayerId : playerIds) {
			// 推送
			PlayingRole pr = SessionManager.getInstance().getPlayer(aPlayerId);
			if (pr != null && pr.isChannelActive()) {
				List<Byte> cardList = ddzRound.getCards().get(playerIndex++);
				pushMsg.my_cards = ArrayUtility.toByteArray(cardList);
				pr.writeAndFlush(pushMsg.build(pr.alloc()));
			}
		}
	}

	public void sendNnCalculateFangka(short fee, byte type, List<Integer> players) {
		logger.info("nn kou fangka ,fangka={},type ={}", fee, type);
		String rsLanHost = RoomServer.getInstance().getServerConfig().getHallLanhost();
		int rsLanPort = RoomServer.getInstance().getServerConfig().getHallLanport();
		boolean reconnectRet = RoomServer.getInstance().getLanClientManager().connect(rsLanHost, rsLanPort);
		if (reconnectRet) {
			RoomServer.getInstance().getLanClientManager().sendCalculateFangKa(rsLanHost, rsLanPort, fee, type,
					players);
		} else {
			logger.error("connect 2 roomServer error!rsLanHost={},rsLanPort={}", rsLanHost, rsLanPort);
		}
	}

	public void roundOver(NnRound nnRound) {
		List<Integer> players = nnRound.getPlayerIds();
		if (nnRound.getRoomFee() > 0 && nnRound.getRoomFeeType() == 2) {
			List<Integer> play = new ArrayList<Integer>();
			short score[] = nnRound.getScore();
			int maxPlayerIndex = 0;
			for (int i = 0; i < score.length; i++) {
				if (score[i] == maxPlayerIndex)
					play.add(players.get(i));
				
				if (score[i] > maxPlayerIndex) {
					play.clear();
					play.add(players.get(i));
					maxPlayerIndex = score[i];
				}
				
			}
			int fee = nnRound.getRoomFee();
			sendNnCalculateFangka((short) fee, nnRound.getRoomFeeType(), play);
		}

		for (Integer aPlayerId : players) {
			NnDataManager.getInstance().removePlayer(aPlayerId);
		}
	}

	public static void main(String[] args) {
		byte[] myCards_raw = { 0x2C, 0x0B, 0x2B, 0x14, 0x12 };
		byte[] otherCards_raw = { 0x31, 0x32, 0x11, 0x02, 0x21 };
		boolean FirstOX = NnAlgorithm.getInstance().GetOxCard(myCards_raw, NnConstants.MAX_COUNT);
		boolean NextOX = NnAlgorithm.getInstance().GetOxCard(otherCards_raw, NnConstants.MAX_COUNT);
		boolean isMyBigger = NnAlgorithm.getInstance().CompareCard(myCards_raw, otherCards_raw, NnConstants.MAX_COUNT,
				FirstOX, NextOX);
		System.out.println(isMyBigger);
	}

}
